/* eslint-disable react/jsx-no-bind */
import { Card } from 'antd'
import { useCallback, useState } from 'react'
import { render } from 'react-dom'
import { Switch, BrowserRouter as Router, Link } from 'react-router-dom'

import { Provider, Route, ErrorBoundary } from '@slardar/react'

import { TriggerEvent } from './event'
import { JsError } from './js-error'
import { Libra } from './libra'
import { TriggerPageview } from './pageview'
import { Pause } from './pause'

declare global {
  interface Window {
    SdkClient: typeof import('@slardar/web').default
  }
}

const ErrorComponent = () => {
  if (new URL(location.href).searchParams.get('err')) {
    throw Error('react err')
  }
  return null
}

const $root = document.querySelector('#app')
const start = () => {
  window.SdkClient('start')
}

const triggerCreateAndStart = () => {
  window.SdkClient('on', 'init', () => {
    const newClient = window.SdkClient.create!()
    newClient.init({
      bid: '666',
      domain: 'cypress.test',
    })
    newClient.start()
  })
}

const configNewPid = () => {
  window.SdkClient.config({
    pid: 'new pid',
  })
}

const triggerCustomEvent = () => {
  window.SdkClient('sendEvent', {
    name: 'custom-event',
    metrics: {
      a: 3,
    },
    categories: {
      b: '3',
    },
  })
}

const triggerCustomLog = () => {
  window.SdkClient('sendLog', {
    content: 'custom-event',
    extra: {
      a: 3,
      b: '3',
    },
    level: 'error',
  })
}

const triggerCapture = () => {
  window.SdkClient('captureException', new Error('manual captureException'), { extraKey: 'extra info' })
}

const triggerCaptureWithOutExtra = () => {
  window.SdkClient('captureException', new Error('captureException with out extra'))
}

const triggerDestroy = () => {
  window.SdkClient('destroy')
}

const triggerCustomPerfMetric = () => {
  window.SdkClient('sendCustomPerfMetric', {
    name: 'test',
    value: 1,
    extra: {
      isRender: 'no',
    },
  })
}

const onClickLongTask = () => {
  const time = Date.now()
  // eslint-disable-next-line no-constant-condition
  while (true) {
    if (Date.now() - time > 50) {
      break
    }
  }
}

const triggerSenderSetSize = () => {
  window.SdkClient('on', 'init', () => {
    window.SdkClient?.getSender()?.setSize(50)
    window.SdkClient('sendEvent', {
      name: 'set-size',
      metrics: {
        size: window.SdkClient?.getSender()?.getSize() || 0,
      },
    })
  })
}

const triggerSenderSetWait = () => {
  window.SdkClient('on', 'init', () => {
    window.SdkClient?.getSender()?.setWait(1500)
    window.SdkClient('sendEvent', {
      name: 'set-wait',
      metrics: {
        wait: window.SdkClient?.getSender()?.getWait() || 0,
      },
    })
  })
}

const triggerContextSetonInit = () => {
  window.SdkClient('on', 'init', () => {
    window.SdkClient?.context?.set('test', '1111')
    window.SdkClient('sendEvent', {
      name: 'set-context',
      categories: window.SdkClient?.context?.toString(),
    })
  })
}

const onClickRAFError = () => {
  window.requestAnimationFrame(() => {
    throw new Error('raf error')
  })
}

const onClickRICError = () => {
  window.requestIdleCallback(() => {
    throw new Error('ric error')
  })
}

const onClickEventHandlerError = () => {
  document.body.addEventListener('click', () => {
    throw new Error('click error')
  })

  document.body.click()
}

const onClickXHRError = () => {
  const xhr = new XMLHttpRequest()
  xhr.open('GET', 'unexist')
  xhr.onreadystatechange = () => {
    throw new Error('xhr error')
  }
  xhr.send()
}

const init = () => {
  window.SdkClient('init', Cypress.env().config)
}

const initInSetTimeout = () => {
  setTimeout(() => {
    window.SdkClient('init', Cypress.env().config)
  }, 200)
}

const createNewInstanceWithBlankScreen = () => {
  const instance = window.SdkClient.create!()
  setTimeout(() => {
    const { bid, pid, domain } = Cypress.env().config
    instance.init({
      bid,
      pid,
      domain,
      plugins: {
        blankScreen: {},
      },
    })
  }, 200)
}
const createNewInstanceWithBlankScreenAndAction = () => {
  const instance = window.SdkClient.create!()
  setTimeout(() => {
    const { bid, pid, domain } = Cypress.env().config
    instance.init({
      bid,
      pid,
      domain,
      plugins: {
        action: {},
      },
    })
  }, 500)
}

const reloadJsErrorPlugin = () => {
  setTimeout(() => {
    window.SdkClient.reloadPlugin!('jsError', {})
  }, 500)
}

const reloadBlankScreenPlugin = () => {
  setTimeout(() => {
    window.SdkClient.reloadPlugin!('blankScreen', {})
  }, 500)
}

const triggerXHR2Filter = () => {
  window.SdkClient('setFilter', 'xhr', ([, url]) => {
    if (url.includes('/oncollect/http')) return true
    return false
  })
}

const triggerFetchFilter = () => {
  window.SdkClient('setFilter', 'fetch', ([, options]) => {
    if (options.body) return true
    return false
  })
}

const triggerErrorFilter = () => {
  window.SdkClient('setFilter', 'err', () => false)
}

const App = () => {
  const [state, setState] = useState({ a: { b: '3' } })
  const onClickBlank = useCallback(() => {
    setState(3 as any)
  }, [])

  return (
    <div className="app">
      <style>
        {`* {
          margin: 0;
          padding: 0
        }`}
      </style>
      <Card>
        <h1>Slardar SDK</h1>
        <p>Testing by cypress</p>
        <button id="init" onClick={init}>
          Init
        </button>
        <button id="init-in-settimeout" onClick={initInSetTimeout}>
          init-in-settimeout
        </button>
        <button id="start" onClick={start}>
          Start
        </button>
        <button id="trigger-create-and-start" onClick={triggerCreateAndStart}>
          trigger-create-and-start
        </button>
        <button id="config-new-pid" onClick={configNewPid}>
          config-new-pid
        </button>
        <button id="longtask_click" onClick={onClickLongTask}>
          LongTask_Click
        </button>
        <TriggerEvent />
        <TriggerPageview />
        <Pause />
        <Libra />
        <JsError />
        <button id="trigger-custom-event" onClick={triggerCustomEvent}>
          trigger-custom-event
        </button>
        <button id="trigger-custom-log" onClick={triggerCustomLog}>
          trigger-custom-log
        </button>
        <button id="trigger-capture" onClick={triggerCapture}>
          trigger-capture
        </button>
        <button id="trigger-capture-without-extra" onClick={triggerCaptureWithOutExtra}>
          trigger-capture-without-extra
        </button>
        <button id="trigger-destroy" onClick={triggerDestroy}>
          trigger-destroy
        </button>
        <button id="trigger-custom-perf-metric" onClick={triggerCustomPerfMetric}>
          trigger-custom-perf-metric
        </button>
        <button id="trigger-sender-setSize" onClick={triggerSenderSetSize}>
          trigger-sender-setSize
        </button>
        <button id="trigger-sender-setWait" onClick={triggerSenderSetWait}>
          trigger-sender-setWait
        </button>
        <button id="trigger-context-set-on-init" onClick={triggerContextSetonInit}>
          trigger-context-set-on-init
        </button>
        <div id="raf_error" onClick={onClickRAFError}>
          RAF error
        </div>
        <div id="ric_error" onClick={onClickRICError}>
          ric error
        </div>
        <div id="click_error" onClick={onClickEventHandlerError}>
          click error
        </div>
        <div id="xhr_error" onClick={onClickXHRError}>
          xhr error
        </div>
        <div id="blank_click" onClick={onClickBlank}>
          Blank_Click
          {state.a.b}
        </div>
        <div id="create_new_instance_blank" onClick={createNewInstanceWithBlankScreen}>
          create new instance with blankScreen
        </div>
        <div id="create_new_instance_blank_action" onClick={createNewInstanceWithBlankScreenAndAction}>
          create new instance with blankScreen and action
        </div>
        <div id="reload-jsError" onClick={reloadJsErrorPlugin}>
          reload jsError plugin
        </div>
        <div id="reload-blankScreen" onClick={reloadBlankScreenPlugin}>
          reload blankScreen plugin
        </div>
        <button id="trigger-set-xhr-2-filter" onClick={triggerXHR2Filter}>
          trigger-set-xhr-2-filter
        </button>
        <button id="trigger-set-fetch-filter" onClick={triggerFetchFilter}>
          trigger-set-fetch-filter
        </button>
        <button id="trigger-set-error-filter" onClick={triggerErrorFilter}>
          trigger-set-error-filter
        </button>
      </Card>
      <Provider Slardar={window.SdkClient}>
        <ErrorBoundary>
          <ErrorComponent />
        </ErrorBoundary>
        <Router>
          <div>
            <nav>
              <ul>
                <li>
                  <Link id="link-home" to="/home">
                    Home
                  </Link>
                </li>
                <li>
                  <Link id="link-about" to="/about">
                    About
                  </Link>
                </li>
                <li>
                  <Link id="link-users" to="/users">
                    Users
                  </Link>
                </li>
              </ul>
            </nav>
            <Switch>
              <Route path="/about" pid="about">
                about
              </Route>
              <Route path="/users" pid="users" render={() => 'users'} />
              <Route path="/home" pid="home" component={Card} />
            </Switch>
          </div>
        </Router>
      </Provider>
    </div>
  )
}

const delay = new URL(location.href).searchParams.get('delay')
if (delay) {
  setTimeout(() => {
    render(<App />, $root!)
  }, parseInt(delay))
} else {
  render(<App />, $root!)
}
